package com.qf.smsplatform.service.Impl;
/*2021/10/30*/

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qf.smsplatform.cache.TAcountRecordCache;
import com.qf.smsplatform.cache.TMultipleParamsCache;
import com.qf.smsplatform.constans.ResultCode;
import com.qf.smsplatform.events.TAcountRecordEvent;
import com.qf.smsplatform.exception.AddDataException;
import com.qf.smsplatform.exception.DeleteDataException;
import com.qf.smsplatform.mapper.TAcountRecordMapper;
import com.qf.smsplatform.pojo.*;
import com.qf.smsplatform.service.TAcountRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @YuTao
 */
@Service
@Transactional          //付款记录表的业务层操作
public class TAcountRecordServiceImpl implements TAcountRecordService {

    private TAcountRecordMapper acountRecordMapper;
    private TMultipleParamsCache multipleParamsCache;
    private TAcountRecordCache tAcountRecordCache;
    private ApplicationContext context;

    @Autowired
    public void setMultipleParamsCache(TMultipleParamsCache multipleParamsCache) {
        this.multipleParamsCache = multipleParamsCache;
    }
    @Autowired
    public void setAcountRecordMapper(TAcountRecordMapper acountRecordMapper) {
        this.acountRecordMapper = acountRecordMapper;
    }
    @Autowired
    public void settAcountRecordCache(TAcountRecordCache tAcountRecordCache) {
        this.tAcountRecordCache = tAcountRecordCache;
    }
    @Autowired
    public void setContext(ApplicationContext context) {
        this.context = context;
    }

    @Override       //付款记录表的分页显示
    public PageInfo<TAcountRecord> selectPage(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<TAcountRecord> acountRecords = tAcountRecordCache.getAllData();
        //拿到当前登录用户的个人信息
        MyAuthUser principal =(MyAuthUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<TAcountRecord> collect = acountRecords.stream()
                .filter(acountRecord->{//过滤出只有用户自己才能够看到订单信息
                    return  principal.getType()==acountRecord.getClientId()||principal.getType()==1 ;
                })
                .skip((pageNum - 1) * pageSize)
                .limit(pageSize)
                .collect(Collectors.toList());
        PageInfo<TAcountRecord> pageInfo=new PageInfo<>(collect);
        return pageInfo;
    }

    @Override//添加一条订单信息
    public void insertTAcount(TAcountRecord tAcountRecord) {
        //判断添加信息是否为空
        if (tAcountRecord.isNull(CheckType.ADD)) {
            throw new AddDataException("添加的数据不合法", ResultCode.DATA_ISNULL);
        }
        //调用业务进行添加
        acountRecordMapper.insertTAcount(tAcountRecord);

        //声明一个事件，添加后对缓存进行更新
        context.publishEvent(new TAcountRecordEvent());

    }

    @Override   //修改一条订单信息
    public void updateTAcount(TAcountRecord tAcountRecord) {
        //判断修改信息是否为空
        if (tAcountRecord.isNull(CheckType.UPDATE)) {
            throw new AddDataException("修改的数据不合法", ResultCode.DATA_ISNULL);
        }
        acountRecordMapper.updateTAcount(tAcountRecord);

        //声明一个事件，修改后进行缓存数据的更新
        context.publishEvent(new TAcountRecordEvent());
    }

    @Override   //删除一条订单信息
    public void deleteTAcount(Long id) {
        //当前登录用户的信息
        MyAuthUser user = (MyAuthUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        //拿到被删除的订单信息
        TAcountRecord byKey = tAcountRecordCache.getByKey(id);
        if(user.getType()==2||byKey.getClientId()!=user.getId()){//判断用户是否有权限进行删除
            throw new DeleteDataException("当前用户没有权限进行数据的删除", ResultCode.NOT_ALLOW);
        }
        acountRecordMapper.deleteTAcount(id);

        //声明一个事件,更新缓存中的数据
        context.publishEvent(new TAcountRecordEvent());
    }

    @Override       //动态参数查询，从客户端传过来的数据，我们根据数据库中的权限条件进行选择使用
    public PageInfo<TAcountRecord> selectByMultParams(TAcountRecord tAcountRecord) throws IllegalAccessException, InstantiationException {

        //从数据库中拿到我们允许查询的参数信息
        TMultipleParams tMultipleParams = multipleParamsCache.getByKey("t_acount_record");
        //按照分隔符进行参数分割,放在集合中对前端传递的对象进行重新封装
        List<String> allowParams=new ArrayList<>();
        String params = tMultipleParams.getParams();
        String[] split = params.split(",");
        for (int i = 0; i < split.length; i++) {
            allowParams.add(split[i]);//遍历放入集合中便于操作
        }
        //通过类的对象获取类对象
        Class<? extends TAcountRecord> recordClass = tAcountRecord.getClass();
        //通过类对象创建一个实例
        TAcountRecord instance = recordClass.newInstance();
        allowParams.forEach(name->{
                //从指定类中获取指定名字的属性
                try {
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(name, recordClass);//属性名，从哪个类拿属性
                Method readMethod = propertyDescriptor.getReadMethod();//读方法 就是 get 方法
                Method writeMethod = propertyDescriptor.getWriteMethod();//写方法就是 set 方法
                    //执行写方法，将前端传递过来的对象中读出来需要的属性，写入到新创建的实例当中
                writeMethod.invoke(instance,readMethod.invoke(tAcountRecord));

                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IntrospectionException e) {
                    e.printStackTrace();
                }
            });
        List<TAcountRecord> acountRecords = acountRecordMapper.selectByMultParams(instance);
        PageInfo<TAcountRecord> pageInfo=new PageInfo<>(acountRecords);

        return pageInfo;

    }


}
